package cussocket

import (
	"fmt"
	"net"
	"net/http"
	"strings"
	"time"
	"zjhk/global"
	"zjhk/model/common/response"

	"github.com/gin-gonic/gin"
	"github.com/gorilla/websocket"
)

type WsApi struct{}

var upgrader = websocket.Upgrader{
	ReadBufferSize:  1024,
	WriteBufferSize: 1024,
	CheckOrigin:     func(r *http.Request) bool { return true },
}

func (w *WsApi) WsHandler(c *gin.Context) {
	// const connLimit = 5
	// var connCount = 0
	conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
	if err != nil {
		response.FailWithMessage("websocket升级失败", c)
		return
	}
	clientIP := getClientIP(c)

	// for _, client := range global.KPR_WS.Clients {
	// 	if strings.Contains(client.ID, clientIP) {
	// 		connCount = connCount + 1
	// 	}
	// }
	// if connCount > connLimit {
	// 	response.FailWithMessage("current ip connection number gt 5", c)
	// 	return
	// }
	clientID := fmt.Sprintf("%d%s", time.Now().UnixNano(), clientIP) // 简单的客户端ID生成方式，实际应用中可能需要更复杂的逻辑
	client := &global.Client{
		ID:         clientID,
		Conn:       conn,
		InChan:     make(chan *global.Message),
		OutChan:    make(chan *global.Message),
		CloseChan:  make(chan byte),
		Subscribes: make(map[string]interface{}),
		Server:     global.KPR_WS,
	}
	global.KPR_WS.AddClient <- client
	// response.OkWithMessage("websocket升级成功", c)
}

// getClientIP 从 Gin 上下文中获取客户端的 IP 地址
func getClientIP(c *gin.Context) string {
	// 尝试从 X-Forwarded-For 头部获取 IP 地址（适用于反向代理场景）
	xff := c.GetHeader("X-Forwarded-For")
	if xff != "" {
		// X-Forwarded-For 头部可能包含多个 IP 地址，取第一个
		ips := stringSplitN(xff, ",", 1)
		return strings.TrimSpace(ips[0])
	}

	// 直接从 RemoteAddr 获取 IP 地址
	remoteAddr, _, err := net.SplitHostPort(c.Request.RemoteAddr)
	if err != nil {
		return ""
	}

	return remoteAddr
}

// stringSplitN 分割字符串，返回最多 n 个子字符串
func stringSplitN(s, sep string, n int) []string {
	a := make([]string, 0, n)
	count := 0
	for {
		idx := strings.Index(s, sep)
		if idx == -1 {
			a = append(a, s)
			break
		}
		a = append(a, s[:idx])
		s = s[idx+len(sep):]
		count++
		if count >= n {
			a = append(a, s)
			break
		}
	}
	return a
}
